iT邦幫忙

2022 iThome 鐵人賽

DAY 21
0
Mobile Development

關於 Flutter 開發的一些設計雜談系列 第 21

Day 21 - 避免讓資料源綁架程式

  • 分享至 

  • xImage
  •  

不管是前端或是後端,我們總有許許多多時候會需要存取外部資源,以 App 來說,大多時候我們都會需要呼叫外部 API,獲取當前頁面所需要的資料。外部 API 的種類則有許多形式,例如最常見的 Web API、各種 Firebase 套件提供的方法,或者是 sqlite。

舉個例子

假設我們正在寫一個顯示最新新聞的 App,在 App 被打開時,App 會使用後端 API 撈取最新幾筆的新聞,並顯示在畫面上。

it_img_19_1.png
https://dartpad.dev/?id=f4078ffd93946af325b8d30ce6fa2584

上面的程式碼乍看之下好像沒什麼問題,但是仔細想想就會發現,這段程式違反了 DIP 原則。我們讀取資料的邏輯緊緊地與呼叫外部 API 程式碼綁在一起。其中造成許多問題,而其中一個問題是,當我們想要改成資料從 sqlite 讀取時,由於 sqlite 類別有著不同的方法,我們就會被迫修改 initState 中的呼叫。

it_img_19_2.png

與第一段程式碼相比,我們不只把 HttpDataSource 換成了 SqliteDataSource,也把呼叫的方法換成 queryNews 了。

用 Repository 改善

為了解決這個問題,我們可以引入 Repository Pattern 來處理。定義一個 NewsRepository 介面,在介面中宣告存取資料的方法,並透過給定實作類別,決定到底是要打 Web API 拿資料,或者是從 Sqlite 讀取。

Repository:Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.

it_img_19_3.png
https://dartpad.dev/?id=31cada35220319817d6a66e06ab6a926

透過實作這個模式,當我們想換實作時,只在修改實作的類別,就可以輕鬆切換。因為使用的地方是依照介面來呼叫的,所以當不同資料源的類別都實作相同介面,我們就不用修改其他程式碼,只要切換實作類別即可。

用狀態管理轉接

在上面的例子中,我們都是直接在 Widget 中使用 Repositroy,但是這種為了讓例子變得簡潔的作法。在真實情況中,大多時候我們會使用狀態管理套件去存取 Repository,當狀態管理套件取得資料時,再通知 Widget 更新畫面。通常我們不會讓 Widget 直接存取 Repository。

若用 flutter_bloc 來修改上面的例子,我們建立了一個 NewsCubit,並在裡頭使用 NewsRepository 這個介面去存取資料,然後再建構子決定使用哪種 DataSource。

it_img_19_4.png

最後則是畫面會監聽 NewsCubit 的狀態,並依據狀態即時更新畫面,顯示新聞

it_img_19_6.png
https://dartpad.dev/?id=63b00dc1b668d8094108c505f11abe4f

利用以上作法,當我們想抽換 Repository 實作時,只要到 NewsCubit 中修改即可,至於使用 NewsRepository 的地方無需修改。

結論

其實 Repository 被廣泛運用在各類應用程式中,不只是 Flutter,像是 Android 官方推薦的架構中,也可以看到 Repository 身影,透過墊了一層 Repository 隔開了商業邏輯與資料存取。


上一篇
Day 20 - 讓設計與程式碼統一
下一篇
Day 22 - 使用依賴注入套件
系列文
關於 Flutter 開發的一些設計雜談30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言